package com.wolfpire.workflow.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.model.Activity;
import org.jbpm.api.model.Transition;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.env.EnvironmentFactory;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.id.DbidGenerator;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.model.TransitionImpl;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import com.wolfpire.workflow.model.TransTypeData;
import com.wolfpire.workflow.om.Node;
import com.wolfpire.workflow.spring.NodeService;


public class JbpmUtil {
	
	static Logger logger = Logger.getLogger(JbpmUtil.class);

	/**
	 * 根据文件名部署新流程定义
	 * @param repositoryService
	 * @param resourceName
	 * @return 流程定义ID
	 */
	public static String deployProcessDefinition(RepositoryService repositoryService, String resourceName)  {
		File file = new File(resourceName);
		String deployId = repositoryService.createDeployment().addResourceFromFile(file).deploy();
		return deployId;
	}
	
	/**
	 * 获取JBPM流程定义
	 * @param processEngine
	 * @param processDefinitionId
	 * @return
	 */
	public static ProcessDefinitionImpl getPdi(ProcessEngine processEngine, String processDefinitionId){
		return (ProcessDefinitionImpl) processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(processDefinitionId).uniqueResult();
	}
	
	/**
	 * 根据流程实例
	 * @param ex
	 * @return
	 */
	public static Integer getDeploymentId(ProcessEngine processEngine, ExecutionImpl ex){
		return (Integer) ex.getVariable("deploymentId");
		
	}
	
	
	
	
	/**
	 * 根据任务获取实例ID
	 * @param task
	 * @return
	 */
	public static Long getInstanceIdByTask(TaskImpl task) {
	
		return Long.valueOf(task.getProcessInstance().toString().split("\\.")[1].split("\\]")[0]);
	}
	
	/**
	 * 获取JBPM序列ID
	 * @param processEngine
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static long getNextId(ProcessEngine processEngine){
		EnvironmentImpl env = ((EnvironmentFactory)processEngine).openEnvironment();
		long dbId = env.getFromCurrent(DbidGenerator.class).getNextId();
		env.close();
		return dbId;
	}
	
	/**
	 * 获取上一节点名称
	 * @param pdi 流程定义
	 * @param curNodeName 当前节点名称
	 * @return
	 */
	public static String getBeforeNodeName(ProcessDefinitionImpl pdi, String curNodeName){
		List<? extends Activity> list = pdi.getActivities();
		for (int i = 0, len = list.size(); i < len; i++) {
			Activity activity = list.get(i);
			if(curNodeName.equals(activity.getName())){
				return list.get(i-1).getName();
			}
		} 
		
		return null;
	}
	
	/**
	 * 自由流动态审批(动态转向某个节点)
	 * @param task 当前任务节点
	 * @param destActivityName 源节点名称
	 * @param createTransitionName 目标节点名称
	 */
	public static void dynamicCreateTransiton(Task task, String destActivityName,
			String createTransitionName ,ProcessEngine processEngine) {
		// 这里不会影响事物
		EnvironmentImpl envImpl = ((EnvironmentFactory) processEngine).openEnvironment();
		try {
			// 动态回退
			ExecutionImpl e = (ExecutionImpl) processEngine.getExecutionService().findExecutionById(task.getExecutionId());
			ActivityImpl currentActivityImpl = e.getActivity();

			ProcessDefinitionImpl processDefinitionImpl = currentActivityImpl.getProcessDefinition();
			// 生成一个transition
			ActivityImpl destActivityImpl = processDefinitionImpl.findActivity(createTransitionName);
			TransitionImpl toApply = currentActivityImpl.createOutgoingTransition();
			toApply.setSource(currentActivityImpl);
			toApply.setDestination(destActivityImpl);
			toApply.setName(createTransitionName);
			processEngine.getTaskService().completeTask(task.getId(), createTransitionName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			envImpl.close();
		}
	}
	
	/**
	 * 获取节点的类型
	 * @param defxml
	 * @param nodeName
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String getNodeType(String defxml , String nodeName){
		String nodeType = "";
		try{
			Element element = DocumentHelper.parseText(defxml).getRootElement();
			Iterator it = element.elements().iterator();
			while(it.hasNext()){
				Element el = (Element)it.next();
				if(el.attribute("name") != null){
					String nameVal = el.attributeValue("name");
					if(nameVal.equals(nodeName)){
						nodeType =  el.getQName().getName();
						return nodeType;
					}
				}
			}
		}catch(Exception e){
			
		}
		
		return nodeType;
	}
	
	/***********************************************************************************/
	/**
	 * 获取当前节点进入的节点 
	 * @param actImpl
	 */
	@SuppressWarnings("unchecked")
	public static List<TransTypeData> getNodeIncomingAndOutgoingTrans(ActivityImpl actImpl,List<TransTypeData> ls_tras,String transType) {
		
		//List<TransTypeData> ls_tras = new ArrayList<TransTypeData>();
		
		if("in".equals(transType)){
			if (!actImpl.getIncomingTransitions().isEmpty()) {
				List<TransitionImpl> inTras = (List<TransitionImpl>) actImpl.getIncomingTransitions();
				for (TransitionImpl transitionImpl : inTras) {
					ActivityImpl pactivity = transitionImpl.getSource();
					if(!pactivity.getIncomingTransitions().isEmpty()){
						String inNodeName = transitionImpl.getSource().getName();
						TransTypeData transData = new TransTypeData();
						transData.setTransType(1);
						transData.setTransName(inNodeName);
						ls_tras.add(transData);
						getNodeIncomingAndOutgoingTrans(pactivity,ls_tras,transType);
					}
					
				}
			}
			return ls_tras;
		}
		
		if("out".equals(transType)){
			if(!actImpl.getOutgoingTransitions().isEmpty()){
				List<TransitionImpl> outTras = (List<TransitionImpl>) actImpl.getOutgoingTransitions();
				for (TransitionImpl transitionImpl : outTras) {
					ActivityImpl pactivity = transitionImpl.getDestination();
					if(!pactivity.getOutgoingTransitions().isEmpty()){
						String outNodeName = transitionImpl.getDestination().getName();
						TransTypeData transData = new TransTypeData();
						transData.setTransType(0);
						transData.setTransName(outNodeName);
						ls_tras.add(transData);
						getNodeIncomingAndOutgoingTrans(pactivity,ls_tras,transType);
					}
				}
			}
			return ls_tras;
		}
		
		return null;
	}
	
	/**
	 * 移除转移
	 * @param pd
	 * @param sourceName
	 * @param destName
	 */
	@SuppressWarnings("unchecked")
	public static void removeOutTransition(ProcessDefinitionImpl pd,
			String sourceName, String destName) {
		ActivityImpl sourceActivity = pd.findActivity(sourceName);
		List<Transition> trans = (List<Transition>) sourceActivity
				.getOutgoingTransitions();
		for (Transition tran : trans) {
			if (destName.equals(tran.getDestination().getName())) {
				trans.remove(tran);
				break;
			}
		}
	}
	
	
	/**
	 * 添加转移
	 * @param pd
	 * @param sourceName
	 * @param destName
	 */
	public static ActivityImpl addOutTransition(ProcessDefinitionImpl pd,String sourceName,String destName){  
	    ActivityImpl sourceActivity = pd.findActivity(sourceName);  
	    ActivityImpl destActivity=pd.findActivity(destName);  
	    TransitionImpl transition = sourceActivity.createOutgoingTransition();  
	    transition.setName("to " +destName);  
	    //transition.setName(destName);
	    transition.setDestination(destActivity);  
	    sourceActivity.addOutgoingTransition(transition);  
	    return sourceActivity;
	}
	
	@SuppressWarnings("unchecked")
	public static List<Node> getNextActivity(String taskName, String flowXml, Long deploymentId, NodeService nodeService){
		List<Node> nodes = new ArrayList<Node>();
		
		try {
			Document doc = DocumentHelper.parseText(flowXml);
			Element root = doc.getRootElement();//获取根节点
			//Node node = null;
			/* 解析任务节点 */
			Iterator<Element> nodeIterator = root.elementIterator();	 
			while(nodeIterator.hasNext()) {
				
				Element el = (Element)nodeIterator.next(); 
				String nodeName = el.attributeValue("name");
				if(taskName.equals(nodeName)){
					Iterator<Element> tranIterator =  el.elementIterator("transition");
					//<transition name="to 网格人员处理" to="网格人员处理"/>
					while (tranIterator.hasNext()) {
						Element tranEl = (Element)tranIterator.next(); 
						logger.info("to--"+ tranEl.attributeValue("to"));
						Node node = nodeService.getNode(deploymentId, tranEl.attributeValue("to"));
			
						nodes.add(node);
					}
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
			return null;
		}
		
		return nodes;
		
	}
	
	@SuppressWarnings("unchecked")
	public static List<Node> getRejectNodes(String taskName, String flowXml, Long deploymentId, NodeService nodeService){
		List<Node> nodes = new ArrayList<Node>();
		
		try {
			Document doc = DocumentHelper.parseText(flowXml);
			Element root = doc.getRootElement();//获取根节点
			/* 解析任务节点 */
			Iterator<Element> nodeIterator = root.elementIterator();	 
			while(nodeIterator.hasNext()) {
				
				Element el = (Element)nodeIterator.next(); 
				Iterator<Element> tranIters = el.elementIterator("transition");
				while(tranIters.hasNext()) {
					
					Element trEL = (Element)tranIters.next(); 
					if(trEL.attributeValue("to").equals(taskName)){
						Node node = nodeService.getNode(deploymentId, el.attributeValue("name"));
			
						nodes.add(node);
						System.out.println("nodeName==="+el.attributeValue("name"));
					}
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
			return null;
		}
		
		return nodes;
	}
	
	//String str = "day,&lt;,3,任务节点2|day,==,3,任务节点3|day,&gt;,3,任务节点4";
	public static String resolveExpr(String exprText, Map<String, String> parameter){
		ExpressionParser parser= new SpelExpressionParser();  
		EvaluationContext context = new StandardEvaluationContext();  
		String res = "";
		String[] exprs = exprText.split("\\|");
		for (int i = 0; i < exprs.length; i++) {
			String[] strs = exprs[i].split("\\,");
			Integer val = Integer.parseInt(parameter.get(strs[0]));
			String s = val+strs[1]+strs[2]+"?'"+strs[3]+"':''";
			String out =  parser.parseExpression(replaceHtml(s)).getValue(context, String.class);
			if("".equals(out)){
				continue;
			}
			res = out;
		}


		return res;
	}
	

	protected static String replaceHtml(String flowXml){
		
		return flowXml.replaceAll("&lt;", "<").replaceAll("&gt;", ">");
	}
}
